package router

import (
	"net/http"
	"reflect"
	"strings"

	"github.com/gin-gonic/gin"
)

type Client struct {
	enGine *gin.Engine
}

func (obj *Client) Add(group *gin.RouterGroup, value any) {
	typeOfVal := reflect.TypeOf(value)
	for i := 0; i < typeOfVal.NumMethod(); i++ {
		fun := typeOfVal.Method(i)
		if fun.Type.NumIn() == 2 && fun.Type.In(0).String() == typeOfVal.String() && fun.Type.In(1).String() == "*gin.Context" {
			pps := strings.Split(fun.Name, "_")
			if len(pps) > 1 {
				switch pps[0] {
				case http.MethodGet, http.MethodPost, http.MethodPut, http.MethodPatch,
					http.MethodHead, http.MethodOptions, http.MethodDelete, http.MethodConnect,
					http.MethodTrace:
					if group == nil {
						obj.Handle(pps[0], strings.Join(pps[1:], "_"), func(ctx *gin.Context) {
							params := make([]reflect.Value, 2)
							params[0] = reflect.ValueOf(value)
							params[1] = reflect.ValueOf(ctx)
							fun.Func.Call(params)
						})
					} else {
						group.Handle(pps[0], strings.Join(pps[1:], "_"), func(ctx *gin.Context) {
							params := make([]reflect.Value, 2)
							params[0] = reflect.ValueOf(value)
							params[1] = reflect.ValueOf(ctx)
							fun.Func.Call(params)
						})
					}
				}
			}
		}
	}
}
func (obj *Client) Run(addr ...string) error {
	return obj.enGine.Run(addr...)
}
func (obj *Client) Handle(httpMethod string, relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
	return obj.enGine.Handle(httpMethod, relativePath, handlers...)
}
func (obj *Client) Group(relativePath string, handlers ...gin.HandlerFunc) *gin.RouterGroup {
	return obj.enGine.Group(relativePath, handlers...)
}

func NewClient() *Client {
	return &Client{enGine: gin.Default()}
}
